/******************************************************
*  Copyright(c) pages.ilovezxl.top
*  FileName : gpio_linux.c
*  Author : rivulet.dave
*  Description : GPIO引脚接口stm32平台实现
*  Data : 2020-09-16
******************************************************/

/*********************************************************************
 * INCLUDES
 */

#include "stdrope.h"
#include "util.h"

#include "hallib.h"
#include "halagent.h"

#if (HAL_GPIO == _ENABLE && HAL_PRODUCER == _HAL_STM32_)

#include "log.h"
#include "gpio_stm32.h"

/*********************************************************************
 *  EXTERNAL VARIABLES
 */

/*********************************************************************
 * MACROS
 */

#define MOD_NAME                "HW_GPIO"

/*********************************************************************
 * TYPES
 */

typedef struct _gpio_in_dev
{
    int32_t iGpioIndex;         //对应gpio.h中定义的GPIO INDEX
    GPIO_TypeDef  *pGPIOx;      //io group
    int32_t iPinNum;            //io num
    int32_t iPinState;          //io state
    int32_t (*pfIOSignalRising)(void *arg);          //input io signal appear callback
    int32_t (*pfIOSignalFalling)(void *arg);       //input io signal disappear callback
} GPIO_IN_DEV_S;

typedef struct _gpio_out_dev
{
    int32_t iGpioIndex;         //对应gpio.h中定义的GPIO INDEX
    GPIO_TypeDef  *pGPIOx;      //io group
    int32_t iPinNum;            //io num
    int32_t iPinState;          //io state
}GPIO_OUT_DEV_S;

/*********************************************************************
 * FUNCTIONS DECLARE
 */

static void GPIO_OutputStateInit(void);
static int32_t GPIO_ReadOnceBySTM32(uint32_t uiGpioIndex, uint8_t *pUserBuf, uint32_t uiSize, uint32_t uiFlag);
static int32_t GPIO_WriteOnceBySTM32(uint32_t uiGpioIndex, const uint8_t *pUserData, uint32_t uiSize, uint32_t uiFlag);
static int32_t GPIO_CtrlBySTM32(hd_t hModuleDescriptor, uint32_t uiCmdKey, void *pValue);

/*********************************************************************
 * VARIABLES
 */

static HAL_OPER_S s_stGpioSTM32Object;
static GPIO_IN_DEV_S s_astGpioInput[] = HAL_GPIO_IN_LIST;
static GPIO_OUT_DEV_S s_astGpioOutput[] = HAL_GPIO_OUT_LIST;

/*********************************************************************
 * FUNCTIONS
 */

/**
 *   @Description: GPIO初始化相关接口，指针
 *   @param : NA
 *   @return ：_OK/_ERR
 */
HAL_OPER_S *GPIO_STM32ObjNew(void)
{
    GPIO_OutputStateInit();

    s_stGpioSTM32Object.pThis = &s_stGpioSTM32Object;
    s_stGpioSTM32Object.pfOpen = NULL;
    s_stGpioSTM32Object.pfClose = NULL;
    s_stGpioSTM32Object.pfLock = NULL;
    s_stGpioSTM32Object.pfUnlock = NULL;
    s_stGpioSTM32Object.pfRead = NULL;
    s_stGpioSTM32Object.pfWrite = NULL;
    s_stGpioSTM32Object.pfReadOnce = GPIO_ReadOnceBySTM32;
    s_stGpioSTM32Object.pfWriteOnce = GPIO_WriteOnceBySTM32;
    s_stGpioSTM32Object.pfCtrl = GPIO_CtrlBySTM32;
    
    return &s_stGpioSTM32Object;
}

/**
 *   @Description: GPIO去初始化、退出
 *   @param : NA
 *   @return ：_OK/_ERR
 */
int32_t GPIO_STM32ObjDelete(void)
{
    return _OK;
}

/**
 *   @Description: 读取GPIO引脚状态
 *   @param : uiGpioIndex - GPIO索引
 *   @param : pUserBuf - 缓存
 *   @param : uiSize - 缓存大小
 *   @param : uiFlag - 属性标记
 *   @return: _OK/_ERR 读取的数据大小
 */
static int32_t GPIO_ReadOnceBySTM32(uint32_t uiGpioIndex, uint8_t *pUserBuf, uint32_t uiSize, uint32_t uiFlag)
{

    GPIO_STATE_E *penState = (GPIO_STATE_E *)(pUserBuf);

    if (!pUserBuf || uiSize < sizeof(GPIO_STATE_E))
    {
        return _ERR;
    }

    for (uint32_t i = 0; i < _ARRAY_SIZE(s_astGpioInput); i++)
    {
        if (s_astGpioInput[i].iGpioIndex == uiGpioIndex)
        {
            s_astGpioInput[i].iPinState = HAL_GPIO_ReadPin(s_astGpioInput[i].pGPIOx, s_astGpioInput[i].iPinNum);
            *penState = s_astGpioInput[i].iPinState;
            return sizeof(GPIO_STATE_E);
        }
    }

    for (uint32_t i = 0; i < _ARRAY_SIZE(s_astGpioOutput); i++)
    {
        if (s_astGpioOutput[i].iGpioIndex == uiGpioIndex)
        {
            *penState = s_astGpioOutput[i].iPinState;
            return sizeof(GPIO_STATE_E);
        }
    }
    return _ERR;
}

/**
 *   @Description: 设置GPIO引脚状态
 *   @param uiGpioIndex - GPIO索引
 *   @param pUserData - 要写入的数据
 *   @param uiSize - 数据大小
 *   @param uiFlag - 属性标记
 *   @return ：_OK/_ERR 写入的数据大小
 */
static int32_t GPIO_WriteOnceBySTM32(uint32_t uiGpioIndex, const uint8_t *pUserData, uint32_t uiSize, uint32_t uiFlag)
{
    GPIO_STATE_E enState;
    GPIO_OUT_DEV_S *pstPinOutDev = NULL;
    
    if (!pUserData || uiSize != sizeof(GPIO_STATE_E))
    {
        return _ERR;
    }

    for (uint32_t i = 0; i < _ARRAY_SIZE(s_astGpioOutput); i++)
    {
        if (s_astGpioOutput[i].iGpioIndex == uiGpioIndex)
        {
            pstPinOutDev = &s_astGpioOutput[i];
            break;
        }
    }

    if (NULL == pstPinOutDev)
    {
        return _ERR;
    }

    enState = *(GPIO_STATE_E *)pUserData;
    if (GPIO_HIGH == enState)
    {
        HAL_GPIO_WritePin(pstPinOutDev->pGPIOx, pstPinOutDev->iPinNum, GPIO_PIN_SET);
    }
    else if (GPIO_LOW == enState)
    {
        HAL_GPIO_WritePin(pstPinOutDev->pGPIOx, pstPinOutDev->iPinNum, GPIO_PIN_RESET);
    }
    else
    {
        LOG_ERR(MOD_NAME, "gpio write value invalid:%d\n", enState);
        return _ERR;
    }

    pstPinOutDev->iPinState = enState;
    return sizeof(enState);
}

/**
 *   @Description: HAL层模块参数控制
 *   @param : hModuleDescriptor - 模块描述符
 *   @param : uiCmdKey - 命令关键字
 *   @param : pValue - 数据
 *   @return:_OK/_ERR
 */
int32_t GPIO_CtrlBySTM32(hd_t hModuleDescriptor, uint32_t uiCmdKey, void *pValue)
{
    uint32_t i;
    GPIO_IN_DEV_S *pstPinInDev = NULL;
    HAL_GPIO_CTRL_S *pstCtrlCB = (HAL_GPIO_CTRL_S *)pValue;
    
    if (!pValue)
    {
        return _ERR;
    }

    for (i = 0; i < _ARRAY_SIZE(s_astGpioInput); i++)
    {
        if (s_astGpioInput[i].iGpioIndex == pstCtrlCB->iIdx)
        {
            pstPinInDev = &s_astGpioInput[i];
            break;
        }
    }

    if (NULL == pstPinInDev)
    {
        return _ERR;
    }
    
    if (_GET_BIT(pstCtrlCB->iState, GPIO_RISE_EDGE))
    {
        pstPinInDev->pfIOSignalRising = pstCtrlCB->pfIOSignalCallback;
    }

    if (_GET_BIT(pstCtrlCB->iState, GPIO_FALL_EDGE))
    {
        pstPinInDev->pfIOSignalFalling = pstCtrlCB->pfIOSignalCallback;
    }
    
    return _OK;
}

static void GPIO_OutputStateInit(void)
{
    GPIO_OUT_DEV_S *pstPinOutDev = NULL;
    int32_t i = 0;

    for (i = 0; i < _ARRAY_SIZE(s_astGpioOutput); i++)
    {
        pstPinOutDev = &s_astGpioOutput[i];
        if (!pstPinOutDev->pGPIOx)
        {
            LOG_ERR(MOD_NAME, "gpio output init fail\n");
            continue;
        }

        if (GPIO_HIGH == pstPinOutDev->iPinState)
        {
            HAL_GPIO_WritePin(pstPinOutDev->pGPIOx, pstPinOutDev->iPinNum, GPIO_PIN_SET);
        }
        else if (GPIO_LOW == pstPinOutDev->iPinState)
        {
            HAL_GPIO_WritePin(pstPinOutDev->pGPIOx, pstPinOutDev->iPinNum, GPIO_PIN_RESET);
        }
        else
        {
            LOG_ERR(MOD_NAME, "write state invalid:%d\n", pstPinOutDev->iPinState);
        }
    }
    return;
}

#endif  // HAL_GPIO == _ENABLE && HAL_PRODUCER == _HAL_STM32_

/************************************** The End Of File **************************************/

